package org.example.study.sc.service;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.example.common.snow.SnowIdUtil;
import org.example.study.sc.constant.SecKillConstant;
import org.example.study.sc.dto.SecKillStockUpdateDTO;
import org.example.study.sc.entity.GoodsSecKill;
import org.example.study.sc.entity.GoodsStock;
import org.example.study.sc.entity.OrderItem;
import org.example.study.sc.entity.OrderMaster;
import org.example.study.sc.mapper.OrderMasterMapper;
import org.example.study.sc.rabbitmq.OrderSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @program: rabbitmq-study
 * @description:
 * @Version V1.0.0
 * @author: dazhi
 * @create: 2021-02-01 11:10
 **/
@Service
@Slf4j
public class OrderMasterService extends ServiceImpl<OrderMasterMapper, OrderMaster> {

    @Autowired
    GoodsSekKilService goodsSekKilService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    OrderSender orderSender;


    @Autowired
    OrderItemService orderItemService;

    @Autowired
    GoodsStockService goodsStockService;

    @Transactional
    public void orderGenerate(Long goodsId, Long memberId) {
        GoodsStock goodsStocks = goodsStockService.getByIdForUpdate(goodsId);

        goodsStocks.setLockCount(1);
        goodsStocks.setStockCount(-1);
        goodsStockService.updateStock(goodsStocks);
        // 生成秒杀订单
        OrderMaster order = new OrderMaster();    // 订单信息
        order.setId(SnowIdUtil.getUUID());
        order.setMemberId(memberId);
        order.setOrderType(2);
        order.setStatus(0);
        order.setCreateTime(new Date());

        OrderItem orderItem = new OrderItem();

        orderItem.setOrderId(order.getId());
        orderItem.setGoodsId(goodsId);
       /* orderItem.setGoodsName(goodsSecKill.getGoodsName());*/
        orderItem.setGoodsPrice(new BigDecimal(10));
        orderItem.setQuantity(1);
        orderItem.setCreateTime(new Date());
        order.setTotalAmount(orderItem.getGoodsPrice().multiply(new BigDecimal(orderItem.getQuantity())));

        this.baseMapper.insert(order);
        orderItemService.save(orderItem);

        log.info("创建秒杀订单成功:{}", order.getId());
        // 发送延迟队列，超时订单自动取消 => Test:一分钟自动取消
        orderSender.ttlOrderCancelMsg(order.getId(), 60 * 1000);
        // 订单详情存入缓存中，秒杀成功
        redisTemplate.opsForValue().set(SecKillConstant.orderRedisKey + order.getId(), order, 600);


    }

    @Transactional
    public void orderCancel(Long orderId) {
        // 查询订单状态是否为未支付
        OrderMaster order = this.getById(orderId);
        if (order == null || order.getStatus() != 0) {   // 订单已支付
            return;
        }
        // 取消超时订单->设置订单为交易取消状态 4 （关闭）
        this.baseMapper.updateStatusById(orderId, 4);
        // 获取所有订单商品
        List<OrderItem> orderItems = orderItemService.getByOrderId(orderId);


        List<Long> goodIds = orderItems.stream().map(a -> a.getGoodsId()).distinct().collect(Collectors.toList());
        List<GoodsStock> updateGoodsStocks = goodsStockService.findStocksForUpdate(goodIds);

        orderItems.forEach(orderItem -> {
            updateGoodsStocks.forEach(stock -> {
                if (Objects.equals(orderItem.getGoodsId(), stock.getGoodsId())) {

                    redisTemplate.opsForValue().increment(SecKillConstant.secKillRedisKey.concat(orderItem.getGoodsId().toString()));
                    log.info("redis中{}库存：{}",orderItem.getGoodsId(), redisTemplate.opsForValue().get(SecKillConstant.secKillRedisKey.concat(orderItem.getGoodsId().toString())));
                    log.info("超时订单取消:{},goodIds:{},可用库存:{},锁库存：{}",orderId,stock.getGoodsId(),stock.getStockCount(),stock.getLockCount());
                    stock.setLockCount(-orderItem.getQuantity());
                    stock.setStockCount(orderItem.getQuantity());
                    goodsStockService.updateStock(stock);
                    return;
                }
            });
        });

    }


}
